with Ada.Unchecked_Deallocation;
package body Storage_Streams is

   function Length (
      this : Storage_Stream_Type 
      ) return Stream_Element_Count
   is
      pragma Inline (Length);
   begin
      return this.F_Length;
   end Length;

   procedure Copy_From (
      this : in out Storage_Stream_Type;
      From : in out Root_Stream_Type'Class;
      Size : Stream_Element_Count
      )
   is
      block_size : Stream_Element_Count := Stream_Element_Count'Min(512, Size);
      buffer : Stream_Element_Array(1..Block_Size);
      last : Stream_Element_Offset;
   begin
      loop
         From.Read(buffer, last);
         if last > 0 then
            Storage_Stream_Type'Class(this).Write(buffer(1 .. last));
         end if;
         exit when last < buffer'Last;
      end loop;
   end Copy_From;

   procedure Copy_To (
      this : in out Storage_Stream_Type;
      To   : not null access Root_Stream_Type'Class;
      Size : Stream_Element_Count
      )
   is
      block_size : Stream_Element_Count := Stream_Element_Count'Min(512, Size);
      buffer : Stream_Element_Array(1..Block_Size);
      last : Stream_Element_Offset;
   begin
      loop
         Storage_Stream_Type'Class(this).Read(buffer, last);
         if last > 0 then
            To.Write(buffer(1 .. last));
         end if;
         exit when last < buffer'Last;
      end loop;
   end Copy_To;

   procedure Fill (
      this : in out Storage_Stream_Type'Class;
      Byte : Stream_Element;
      Size : Stream_Element_Count
      )
   is
   begin
      this.Write((1 .. Size => Byte));
   end Fill;

   procedure Fill (
      this : in out Storage_Stream_Type'Class;
      Bytes : Stream_Element_Array;
      Count : Stream_Element_Count
      )
   is
   begin
      for i in 1 .. Count loop
         this.Write(Bytes);
      end loop;
   end Fill;

   procedure Free (P : in out Storage_Stream_Pointer)
   is
      pragma Inline(Free);
      procedure Dispose is
         new Ada.Unchecked_Deallocation (
            Storage_Stream_Type'Class,
            Storage_Stream_Pointer);
   begin
      Dispose(P);
   end Free;

end Storage_Streams;
